package com.lgy.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lgy.enums.LeaveStatusEnum;
import com.lgy.exceptions.BusinessException;
import com.lgy.mapper.LeaveMapper;
import com.lgy.mapper.ProcessEngineMapper;
import com.lgy.mapper.SysUserMapper;
import com.lgy.model.entity.Leave;
import com.lgy.model.entity.ProcessEngineTable;
import com.lgy.model.entity.SysUser;
import com.lgy.model.vo.LeaveVo;
import com.lgy.utils.ResponseResult;
import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.history.HistoricActivityInstance;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.runtime.ActivityInstance;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.UserTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;


@Service
public class LeaveServiceImpl extends ServiceImpl<LeaveMapper, Leave> implements ILeaveService {

    @Autowired
    private ProcessEngineMapper processEngineMapper;
    @Autowired
    private IProcessService processService;
    @Autowired
    private LeaveMapper leaveMapper;
    @Resource
    private TaskService taskService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Resource
    private RuntimeService runtimeService ;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;

    @Override
    public void startLeaveApply(LeaveVo leaveVo,Long applyUserId, Long approvalUserId) {
        LambdaQueryWrapper<ProcessEngineTable> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ProcessEngineTable::getTableName, "my_leave");
        ProcessEngineTable processEngineTable = processEngineMapper.selectOne(lqw);
        String proInstanceId = processService.startProcessFirst(String.valueOf(applyUserId),String.valueOf(approvalUserId),processEngineTable.getProcDefinitionKey());
        // 业务表的数据
        Leave myLeave = new Leave();
        myLeave.setUserId(applyUserId);
        myLeave.setUserName(leaveVo.getApplyUserName());
        myLeave.setDay(leaveVo.getDay());
        myLeave.setStatus(1); // 申请中
        myLeave.setCreateTime(new Date());
        myLeave.setProcInstId(proInstanceId);
        // 启动一个流程实例
        leaveMapper.insert(myLeave);
    }

    @Override
    public ResponseResult listSearch(Page<Leave> page) {
        LambdaQueryWrapper<Leave> queryWrapper = Wrappers.<Leave>lambdaQuery();
        // 按create_time排序
        queryWrapper.orderByDesc(Leave::getCreateTime);
        Page<Leave> pages = this.page(page, queryWrapper);
        List<Map<String, Object>> data = new ArrayList<>();
        Long i = (pages.getPages()-1) * pages.getSize();
        for(Leave leave : pages.getRecords()) {
            i++;
            Map<String, Object> map = new HashMap<>();
            map.put("id", i);
            map.put("leaveId", leave.getId());
            map.put("applyUser", leave.getUserName());
            map.put("day", leave.getDay());
            map.put("status", LeaveStatusEnum.getLeaveStatus(leave.getStatus()));
            map.put("createTime", leave.getCreateTime());

            //获取审批人信息
            if(StringUtils.isBlank(leave.getProcInstId()) || leave.getStatus().intValue() == 3) {
                map.put("approvelUser", "");
            } else {
                Task task = taskService.createTaskQuery().processInstanceId(leave.getProcInstId()).singleResult();
                String sysUserId = task.getAssignee();
                map.put("approvelUser", sysUserMapper.selectById(Long.valueOf(sysUserId)).getUserName());
            }
            data.add(map);
        }
        return ResponseResult.successLayUiList(data, pages.getTotal());
    }

    @Override
    public void approval(Long id, Integer status, SysUser sessionUser) {
        Leave leave = leaveMapper.selectById(id);
        if(StringUtils.isBlank(leave.getProcInstId())) {
            throw new BusinessException("当前数据不能进行审批!");
        } else {
            Task task = taskService.createTaskQuery().processInstanceId(leave.getProcInstId()).singleResult();
            if(!task.getAssignee().equals(sessionUser.getId().toString())) {
                throw new BusinessException("当前审批人不对!");
            }
        }
        if(leave.getStatus().intValue() == 3 || leave.getStatus().intValue() == 2) {
            throw new BusinessException("当前数据不能进行审批!");
        }
        if(status == 1) {
            LambdaQueryWrapper<ProcessEngineTable> lqw = new LambdaQueryWrapper<>();
            lqw.eq(ProcessEngineTable::getTableName, "my_leave");
            ProcessEngineTable processEngineTable = processEngineMapper.selectOne(lqw);
            //通过操作
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processEngineTable.getProcDefinitionKey()).list();
            BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(list.get(list.size()-1).getId());
            Collection<UserTask> userTaskCollection = bpmnModelInstance.getModelElementsByType(UserTask.class);
            Task task = taskService.createTaskQuery().processInstanceId(leave.getProcInstId()).active().singleResult();
            UserTask lastUserTask = userTaskCollection.stream().reduce((first,second) -> second).orElse(null);
            if(lastUserTask.getId().equals(task.getTaskDefinitionKey())) {
                //最后一个用户任务节点进行审批
                leave.setStatus(2);
                leave.setProcInstId("");
                leaveMapper.updateById(leave);
            }
            taskService.complete(task.getId());
        }
        if(status == 2) {
            //驳回到申请人操作
            leave.setStatus(3);
            ActivityInstance activityInstance = runtimeService.getActivityInstance(leave.getProcInstId());
            ActivityInstance[] childActivityInstances = activityInstance.getChildActivityInstances();
            ActivityInstance activityTask = childActivityInstances[0];

            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(leave.getProcInstId())
                    .list();

            HistoricActivityInstance firstTask  = historicActivityInstanceList.stream()
                    .filter(instance -> instance.getEndTime() != null)
                    .min(Comparator.comparing(HistoricActivityInstance::getStartTime).thenComparing(HistoricActivityInstance::getEndTime))
                    .orElse(null);
            runtimeService.createProcessInstanceModification(leave.getProcInstId())
                    .cancelActivityInstance(activityTask.getId())
                    .startBeforeActivity(firstTask.getActivityId())
                    .execute();
            leaveMapper.updateById(leave);
        }
    }
}
